﻿namespace FilteredPageReference
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using EPiServer.Core;
    using EPiServer.Core.PropertySettings;
    using EPiServer.DataAbstraction;
    using EPiServer.Web.WebControls;

    /// <summary>
    /// Filtered page reference property settings UI class
    /// </summary>
    public class PropertyFilteredPageReferencePropertySettingsUI : PropertySettingsControlBase
    {
        private CheckBoxList _filteredPageTypes;
        private InputPageReference _treeStart;
        private CheckBoxList _fullTypeNames;
        private CheckBox _startTreeFromCurrentPage;
        private CheckBox _restrictToEPiServerPages;
        private CheckBox _startFromCurrentSiteStartPage;
        private TextBox _validationMessage;
        private CheckBox _allowQuickEdit;
        private TextBox _popupHeight;
        private TextBox _popupWidth;


        /// <summary>
        /// Adds the new row.
        /// </summary>
        /// <param name="label">The label.</param>
        /// <param name="control">The control.</param>
        protected void AddNewRow(Label label, Control control)
        {
            AddNewRow(label, control, false, null);
        }

        /// <summary>
        /// Adds the new row.
        /// </summary>
        /// <param name="label">The label.</param>
        /// <param name="control">The control.</param>
        /// <param name="scroll">if set to <c>true</c> [scroll].</param>
        protected void AddNewRow(Label label, Control control, bool scroll, List<Control> validationControls)
        {
            Literal literal = new Literal { Text = "<div style=\"clear:both;margin-bottom:5px;padding-bottom:5px;float:left;width:100%\">" };
            Controls.Add(literal);
            literal = new Literal { Text = "<div style=\"width:210px;float:left\">" };
            Controls.Add(literal);
            label.Attributes["style"] = "width:210px!important";
            Controls.Add(label);
            literal = new Literal { Text = "</div>" };
            Controls.Add(literal);
            literal = new Literal { Text = "<div style=\"margin-left:15px;float:left;width:420px;float:left\">" };
            Controls.Add(literal);

            if (scroll)
            {
                literal = new Literal { Text = "<div style=\"width:100%;overflow:auto;padding:3px;border:solid 1px #B4B4B4\">" };
                Controls.Add(literal);
            }

            Controls.Add(control);

            if (validationControls != null)
            {
                foreach (Control validationControl in validationControls)
                    Controls.Add(validationControl);
            }

            if (scroll)
            {
                literal = new Literal { Text = "</div>" };
                Controls.Add(literal);
            }

            literal = new Literal { Text = "</div>" };
            Controls.Add(literal);
            literal = new Literal { Text = "</div>" };
            Controls.Add(literal);
        }

        /// <summary>
        /// Translates the specified element name.
        /// </summary>
        /// <param name="elementName">Name of the element.</param>
        /// <returns></returns>
        private string Translate(string elementName)
        {
            return LanguageHelper.Translate(string.Concat("/filteredPageReference/", elementName));
        }

        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to 
        /// create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            Literal literal = new Literal { Text = "<div class=\"epi-size10\">" };
            Controls.Add(literal);

            literal = new Literal { Text = string.Format("<fieldset><legend>{0}</legend><div class=\"epi-size10\">", Translate("treeStartingPoint")) };
            Controls.Add(literal); 

            // start tree from
            string id = "startTreeFrom";
            _treeStart = new InputPageReference { ID = id };

            Label label = new Label { Text = Translate("startPageTreeFrom"), AssociatedControlID = id };
            AddNewRow(label, _treeStart);

            // start page tree from current page
            id = "startTreeFromCurrentPage";
            _startTreeFromCurrentPage = new CheckBox { ID = id };

            label = new Label { Text = Translate("currentPage"), AssociatedControlID = id };
            AddNewRow(label, _startTreeFromCurrentPage);

            // start page tree from start page in current site
            id = "startTreeFromCurrentSiteStartPage";
            _startFromCurrentSiteStartPage = new CheckBox { ID = id };

            label = new Label { Text = Translate("currentSiteStartPage"), AssociatedControlID = id };
            AddNewRow(label, _startFromCurrentSiteStartPage);

            literal = new Literal { Text = "</div></fieldset>" };
            Controls.Add(literal);

            literal = new Literal { Text = string.Format("<fieldset><legend>{0}</legend><div class=\"epi-size10\">", Translate("pagePickingRestrictions")) };
            Controls.Add(literal); 

            // validation message
            id = "validationErrorMessage";
            _validationMessage = new TextBox { ID = id };

            label = new Label { Text = Translate("validationErrorMessage"), AssociatedControlID = id };
            AddNewRow(label, _validationMessage);

            // restrict to episerver pages
            id = "restrictToEPiServerPages";
            _restrictToEPiServerPages = new CheckBox { ID = id };

            label = new Label { Text = Translate("restrictToEPiServerPages"), AssociatedControlID = id };
            AddNewRow(label, _restrictToEPiServerPages);

            // full type name
            if (Helper.UsingPageTypeBuilder())
            {
                id = "fullTypeNames";
                _fullTypeNames = new CheckBoxList { ID = id }; 

                List<string> typeNames = new List<string>();
                
                foreach (Type type in Helper.GetPageTypeBuilderTypes())
                {
                    if (!typeNames.Contains(type.FullName))
                        typeNames.Add(type.FullName);
                }

                typeNames.Sort();

                foreach (string typeName in typeNames)
                    _fullTypeNames.Items.Add(new ListItem(typeName, typeName));

                label = new Label { Text = Translate("pageTypeBuilderTypesAndInterfaces"), AssociatedControlID = id };
                AddNewRow(label, _fullTypeNames, true, null);
            }

            // filtered page types
            id = "filteredPageTypes";
            _filteredPageTypes = new CheckBoxList { ID = id };

            PageTypeCollection pageTypes = PageType.List();

            foreach (PageType pageType in pageTypes)
                _filteredPageTypes.Items.Add(new ListItem(pageType.Name, pageType.Name.Trim()));

            label = new Label { Text = Translate("pageTypes"), AssociatedControlID = id };
            AddNewRow(label, _filteredPageTypes, true, null);

            literal = new Literal { Text = "</div></fieldset>" };
            Controls.Add(literal);

            // quick editing settings
            literal = new Literal { Text = string.Format("<fieldset><legend>{0}</legend><div class=\"epi-size10\">", Translate("quickEdit")) };
            Controls.Add(literal);

            // allow quick edit
            id = "allowQuickEdit";
            _allowQuickEdit = new CheckBox { ID = id };

            label = new Label { Text = Translate("allowQuickEdit"), AssociatedControlID = id };
            AddNewRow(label, _allowQuickEdit);

            // popup height
            id = "popupHeight";
            _popupHeight = new TextBox() { ID = id };

            label = new Label { Text = Translate("popupHeight"), AssociatedControlID = id };

            List<Control> validationControls = new List<Control>
                                                   {
                                                       new RequiredFieldValidator
                                                           {
                                                               ControlToValidate = id,
                                                               ErrorMessage = "You must enter a popup height",
                                                               Text = "*",
                                                               Display = ValidatorDisplay.Dynamic
                                                           },
                                                       new CompareValidator
                                                           {
                                                               ControlToValidate = id,
                                                               ErrorMessage = "You must enter a valid popup height",
                                                               Text = "*",
                                                               Display = ValidatorDisplay.Dynamic,
                                                               Operator = ValidationCompareOperator.DataTypeCheck,
                                                               Type = ValidationDataType.Integer
                                                           }
                                                   };

            AddNewRow(label, _popupHeight, false, validationControls);

            // popup width
            id = "popupWidth";
            _popupWidth = new TextBox() { ID = id };

            label = new Label { Text = Translate("popupWidth"), AssociatedControlID = id };

            validationControls = new List<Control>
                                     {
                                         new RequiredFieldValidator
                                             {
                                                 ControlToValidate = id,
                                                 ErrorMessage = "You must enter a popup height",
                                                 Text = "*",
                                                 Display = ValidatorDisplay.Dynamic
                                             },
                                         new CompareValidator
                                             {
                                                 ControlToValidate = id,
                                                 ErrorMessage = "You must enter a valid popup height",
                                                 Text = "*",
                                                 Display = ValidatorDisplay.Dynamic,
                                                 Operator = ValidationCompareOperator.DataTypeCheck,
                                                 Type = ValidationDataType.Integer
                                             }
                                     };

            AddNewRow(label, _popupWidth, false, validationControls);


            literal = new Literal { Text = "</div></fieldset>" };
            Controls.Add(literal);

            literal = new Literal { Text = "</div>" };
            Controls.Add(literal);
        }

        /// <summary>
        /// Populates control values
        /// </summary>
        /// <param name="propertySettings">The property settings.</param>
        public override void LoadSettingsUI(IPropertySettings propertySettings)
        {
            EnsureChildControls();

            PropertyFilteredPageReferenceSettings settings = propertySettings as PropertyFilteredPageReferenceSettings;

            if (settings == null)
                return;

            if (!string.IsNullOrEmpty(settings.PageTypeNames))
            {
                List<string> pageTypeNames = settings.PageTypeNames.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();

                foreach (string pageTypeName in pageTypeNames)
                {
                    ListItem listItem = _filteredPageTypes.Items.FindByValue(pageTypeName);

                    if (listItem != null)
                        listItem.Selected = true;
                }
            }

            if (Helper.UsingPageTypeBuilder())
            {
                if (!string.IsNullOrEmpty(settings.FullTypeNames))
                {
                    List<string> fullTypeNames = settings.FullTypeNames.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();

                    foreach (string fullTypeName in fullTypeNames)
                    {
                        ListItem listItem = _fullTypeNames.Items.FindByValue(fullTypeName);

                        if (listItem != null)
                            listItem.Selected = true;
                    }
                }
            }

            _treeStart.PageLink = !PageReference.IsNullOrEmpty(settings.StartFrom) ? settings.StartFrom : PageReference.RootPage;
            _startTreeFromCurrentPage.Checked = settings.StartFromCurrentPage;
            _restrictToEPiServerPages.Checked = settings.RestrictToEPiServerPages;
            _startFromCurrentSiteStartPage.Checked = settings.StartFromCurrentSiteStartPage;
            _validationMessage.Text = settings.ValidationErrorMessage;
            _allowQuickEdit.Checked = settings.AllowQuickEdit;
            _popupHeight.Text = settings.PopupHeight.ToString();
            _popupWidth.Text = settings.PopupWidth.ToString();
        }

        /// <summary>
        /// Updates the settings.
        /// </summary>
        /// <param name="propertySettings">The property settings.</param>
        public override void UpdateSettings(IPropertySettings propertySettings)
        {
            EnsureChildControls();

            PropertyFilteredPageReferenceSettings settings = propertySettings as PropertyFilteredPageReferenceSettings;

            string pageTypeNames = string.Empty;
            pageTypeNames = _filteredPageTypes.Items.Cast<ListItem>().Where(listItem => listItem.Selected).Aggregate(pageTypeNames, (current, listItem) => current + (listItem.Value + ","));

            string fullTypeNames = string.Empty;

            if (Helper.UsingPageTypeBuilder())
                fullTypeNames = _fullTypeNames.Items.Cast<ListItem>().Where(listItem => listItem.Selected).Aggregate(fullTypeNames, (current, listItem) => current + (listItem.Value + ","));

            settings.PageTypeNames = pageTypeNames.TrimEnd(',');
            settings.FullTypeNames = Helper.UsingPageTypeBuilder() ? fullTypeNames.TrimEnd(',') : string.Empty;
            settings.StartFrom = !PageReference.IsNullOrEmpty(_treeStart.PageLink) ? _treeStart.PageLink : PageReference.RootPage;
            settings.StartFromCurrentPage = _startTreeFromCurrentPage.Checked;
            settings.RestrictToEPiServerPages = _restrictToEPiServerPages.Checked;
            settings.StartFromCurrentSiteStartPage = _startFromCurrentSiteStartPage.Checked;
            settings.ValidationErrorMessage = _validationMessage.Text;
            settings.AllowQuickEdit = _allowQuickEdit.Checked;
            settings.PopupHeight = ParseInt(_popupHeight, 700);
            settings.PopupWidth = ParseInt(_popupWidth, 500);
        }

        private int ParseInt(TextBox textBox, int defaultValue)
        {
            int parsedInt;
            return int.TryParse(textBox.Text.Trim(), out parsedInt) ? parsedInt : defaultValue;
        }

    }
}
